home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fritz: All Fritz
/
All Fritz.zip
/
All Fritz
/
FILES
/
PROGNG_C
/
DBTOOLC.LZH
/
SOURCE.ARC
/
DBARRAY.C
next >
Wrap
C/C++ Source or Header
|
1986-10-08
|
24KB
|
1,005 lines
/*
*
* NAME:
* dbarray.c - array function for use from dbase
*
* SYNOPSIS:
* cr_array(id, n, type) -- create an array
* rn_array(id, newid) -- rename an array
* fc_array(id) -- find an array
* arsize(id) -- find size of an array
* fr_array(id) -- free an array
* put_arv(id, index, value)-- put a value in an array
* get_arv(id, index) -- get a value from an array
* st_arrays() -- lists info on all arrays
* dump_array() -- dumps contents of an array
* fdump_array() -- dumps contents of an array to a disk file
* arcount() -- count # elements used so far
* arsetcnt() -- reset count of an array
* aroff() - parses offset dimension expression
* save_arr() - save the array to a disk file
* rest_arr() - restore an array from a disk file
*
* DESCRIPTION:
* Provide basic array management function for dBASE
*
* AUTHOR: J. T. Cooper
*
*/
#include <stdio.h>
#include <ctype.h>
#include "dctmain.h"
#define MAXARRAYS 10 /* max # of arrays in use at one time */
#define MAXDIM 10 /* max # dimensions */
#define BIGARRAY 32000 /* largest # of elements in array */
#define MAXCLEN 255 /* maximum length of character variable */
#define MAXNLEN 8 /* length of numeric variable (same as double)*/
struct
{
char ar_id[11]; /* array id (name) */
char ar_type; /* memory variable type */
int ar_size; /* max # elements in this array */
int ar_count; /* count of # elements used so far */
int ar_ndim; /* # of dimensions created with */
int ar_dims[MAXDIM];
union
{
char **vchar; /* beg of character pointer array */
int *vint; /* beg of array of integers */
double *vdub; /* beg of array of doubles */
} ar_val;
} db_ArrayList[MAXARRAYS];
/*
*
* NAME:
* cr_array - create array for dbase
*
* SYNOPSIS:
* cr_array(id, s, type)
* char *id; -- ASCIIZ name of array
* int s; -- Dimension expression
* CHAR type; -- 'N' or 'C' variable type
*
* DESCRIPTION:
* Creates an array big enough to hold n elements of the
* given type.
*
* RETURNS:
* Returns the actual number of items the array has room for,
* which will be n if enough memory is available, or -1
* if an error occurs.
*
*/
cr_array(id, s, type)
char *id;
char *s;
char type;
{
int i,j;
int n;
/* make sure array name isn't already in use */
for (i = 0; i < MAXARRAYS; i++)
if (strccmp(db_ArrayList[i].ar_id, id) == 0)
{
dctmsg(MSG_IN_USE);
return -1;
}
/* now find an available slot in the db_ArrayList, if any */
for (i = 0; i < MAXARRAYS; i++)
{
if (*db_ArrayList[i].ar_id == '\0')
break;
}
if (i == MAXARRAYS)
{
dctmsg(MSG_NO_MORE);
return -1;
}
/* convert dimensional expression to actual size of array */
for (j = 0, n = 1; *s && j < MAXDIM; s++)
{
db_ArrayList[i].ar_dims[j] = atoi(s);
n *= db_ArrayList[i].ar_dims[j++];
while (isdigit(*s))
s++; /* skip past digits we've already used */
if (toupper(*s) != 'X')
break;
}
db_ArrayList[i].ar_ndim = j;
/* make sure he doesn't try to take over the world */
if (n > BIGARRAY || n < 0)
{
dctmsg(MSG_TOO_MANY);
return -1;
}
db_ArrayList[i].ar_type = toupper(type);
switch (db_ArrayList[i].ar_type)
{
case 'C':
if (n > 16000)
{
dctmsg(MSG_TOO_MANY);
return -1;
}
db_ArrayList[i].ar_val.vchar = (char **)dctalloc(n, sizeof(char *));
if (db_ArrayList[i].ar_val.vchar == NULL)
{
dctmsg(MSG_NO_SPACE);
return(-1);
}
break;
case 'N':
#ifdef LARGE
if (n > 8000)
#else
if (n > 4000)
#endif
{
dctmsg(MSG_TOO_MANY);
return -1;
}
db_ArrayList[i].ar_val.vdub = (double *)dctalloc(n, sizeof(double));
if (db_ArrayList[i].ar_val.vdub == NULL)
{
dctmsg(MSG_NO_SPACE);
return(-1);
}
break;
default:
dctmsg(MSG_INV_TYPE);
return -1;
break;
}
strcpy(db_ArrayList[i].ar_id, id); /* now make it official */
db_ArrayList[i].ar_size = n; /* remember how many we have room for */
db_ArrayList[i].ar_count = 0; /* no elements yet */
return n;
}
/*
*
* NAME:
* rn_array - rename an array
*
* SYNOPSIS:
* rn_array(id, newid)
* char *id; -- ASCIIZ name of array
* char *newid; -- new ASCIIZ name of array
*
* DESCRIPTION:
* Changes the name of the array <id> to <newid>
*
* RETURNS:
* Sets status variable to 0 if successful, -1 if not.
*/
rn_array(id, newid)
char *id, *newid;
{
int i;
/* first see if the array exists */
for (i = 0; i < MAXARRAYS; i++)
{
if (strccmp(db_ArrayList[i].ar_id, id) == 0)
break;
}
if (i == MAXARRAYS)
{
dctmsg(MSG_NO_ARRAY);
return -1;
}
strcpy(db_ArrayList[i].ar_id, newid);
return(0);
}
/*
*
* NAME:
* fc_array - find the c array by a given name.
*
* SYNOPSIS:
* char *fc_array(id)
* char *id; -- name of array to be found
*
* DESCRIPTION:
* Finds the array, if it exists, previously created and
* given the name matching id.
*
* RETURNS:
* Returns a pointer to the first element in the array if
* found, otherwise a NULL pointer is returned.
*
* NOTES:
* Returned value must be coerced to the proper type if the
* array is anything but a character array.
*
*/
char *fc_array(id)
char *id;
{
int i;
for (i = 0; i < MAXARRAYS; i++)
{
if (strccmp(db_ArrayList[i].ar_id, id) == 0)
break;
}
if (i == MAXARRAYS)
{
dctmsg(MSG_NO_ARRAY);
return ((char *) 0);
}
switch (db_ArrayList[i].ar_type)
{
case 'C':
return((char *)db_ArrayList[i].ar_val.vchar);
break;
case 'N':
return( (char *)db_ArrayList[i].ar_val.vdub);
break;
}
return((char *)0);
}
/*
*
* NAME:
* arsize - find the size of an array
*
* SYNOPSIS:
* int arsize(id)
* char *id; -- name of array
*
* DESCRIPTION:
* Determines the size of the array whose name is id.
*
* RETURNS:
* Returns the maximum number of elements for which the
* array was created to hold, or 0 if the array cannot
* be found.
*
*/
arsize(id)
char *id;
{
int i;
for (i = 0; i < MAXARRAYS; i++)
{
if (strccmp(db_ArrayList[i].ar_id, id) == 0)
break;
}
if (i == MAXARRAYS)
return (0);
return(db_ArrayList[i].ar_size);
}
/*
*
* NAME:
* arsetcnt - reset the count of elements in an array
*
* SYNOPSIS:
* int arsetcnt(id, newcnt)
* char *id; -- name of array
* int newcnt; -- new size of array
*
* DESCRIPTION:
* Reset the internal count of the number of elements in
* an array. Added primarily for those
* routines (such as sros) that manipulate members of an
* array outsize of the normal put_arv function.
*
* RETURNS:
* Returns newcnt if successful, 0 if newcnt is greater
* than the maximum elements the array was created to hold.
*
*/
arsetcnt(id,newcnt)
char *id;
int newcnt;
{
int i;
for (i = 0; i < MAXARRAYS; i++)
{
if (strccmp(db_ArrayList[i].ar_id, id) == 0)
break;
}
if (i == MAXARRAYS)
return (0);
if(newcnt > db_ArrayList[i].ar_size) /* count > created size? */
{
dctmsg(MSG_OUT_OF_BOUNDS);
return(0);
}
return(db_ArrayList[i].ar_count = newcnt);
}
/*
*
* NAME:
* arcount - count the # elements used so far (sorta)
*
* SYNOPSIS:
* int arcount(id)
* char *id; -- name of array
*
* DESCRIPTION:
* 'Counts' the number of items which have been placed in an
* array. If the array has unused slots in between actual
* values, those slots will be counted as well. The actual
* mechanism used is to keep track of the largest index
* accessed by the put_arv function. Thus, this function can
* be used to determine the next available slot in the array.
*
* RETURNS:
* Returns the largest index used so far, plus 1. If the array
* does not exist, -1 is returned.
*/
arcount(id)
char *id;
{
int i;
for (i = 0; i < MAXARRAYS; i++)
{
if (strccmp(db_ArrayList[i].ar_id, id) == 0)
break;
}
if (i == MAXARRAYS)
return (-1);
return(db_ArrayList[i].ar_count);
}
/*
*
* NAME:
* fr_array - free array
*
* SYNOPSIS:
* void fr_array(id)
* char *id; -- name of array
*
* DESCRIPTION:
* Frees all storage taken up by the array and its elements.
*
* RETURNS:
* Returns nothing.
*
*/
void fr_array(id)
char *id;
{
int i, j;
/* first find the array, if it exists */
for (i = 0; i < MAXARRAYS; i++)
{
if (strccmp(db_ArrayList[i].ar_id, id) == 0)
break;
}
if (i == MAXARRAYS)
{
/* if the name of the array is 'ALL', he wants to free all the arrays */
if (strccmp(id, "ALL") == 0)
{
for (j = 0; j < MAXARRAYS; j++)
{
if (*db_ArrayList[j].ar_id)
fr_array(db_ArrayList[j].ar_id);
}
}
else
dctmsg(MSG_NO_ARRAY);
return;
}
switch (db_ArrayList[i].ar_type)
{
case 'C':
/* first free up all string space */
for(j = 0; j < db_ArrayList[i].ar_count; j++)
if (db_ArrayList[i].ar_val.vchar[j] != 0)
free(db_ArrayList[i].ar_val.vchar[j]);
/* now free up the array itself */
free(db_ArrayList[i].ar_val.vchar);
break;
case 'N':
free( (char *) db_ArrayList[i].ar_val.vdub);
break;
default:
dctmsg(MSG_INV_TYPE);
break;
}
*db_ArrayList[i].ar_id = '\0'; /* zap the array name */
db_ArrayList[i].ar_size = 0;
db_ArrayList[i].ar_count = 0;
#ifdef LC3
calloc(0,512); /* kludge for Lattice 3.0 sizmem() bug */
#endif
}
/*
* NAME:
* put_arv - put a value into an array
*
* SYNOPSIS:
* int put_arv(id, s, value)
* char *id; -- array name
* char *s; -- offset in array (dimensional expression)
* char *value; -- ASCIIZ representation of value
*
* DESCRIPTION:
* Converts value to the appropriate type, and stores it
* in the array whose name is id, at offset s.
*
* RETURNS:
* Returns index if successful, or -1 if an error occurs.
*
*/
int put_arv(id, s, value)
char *id;
char *s;
char *value;
{
int i;
int index;
/* first see if the array exists */
for (i = 0; i < MAXARRAYS; i++)
{
if (strccmp(db_ArrayList[i].ar_id, id) == 0)
break;
}
if (i == MAXARRAYS)
{
dctmsg(MSG_NO_ARRAY);
return -1;
}
index = aroff(s, db_ArrayList[i].ar_dims);
/* make sure we don't go off the deep end */
if (index >= db_ArrayList[i].ar_size)
{
dctmsg(MSG_OUT_OF_BOUNDS);
return(-1);
}
/* now put the value in the array */
switch (db_ArrayList[i].ar_type)
{
case 'C':
/* first free up any previous storage & reallocate for new string */
if (db_ArrayList[i].ar_val.vchar[index])
free(db_ArrayList[i].ar_val.vchar[index]);
db_ArrayList[i].ar_val.vchar[index] = dctalloc(1,strlen(value)+1);
if (db_ArrayList[i].ar_val.vchar[index] == NULL)
{
dctmsg(MSG_NO_SPACE);
return(-1);
}
strcpy(db_ArrayList[i].ar_val.vchar[index], value);
break;
case 'N':
db_ArrayList[i].ar_val.vdub[index] = atof(value);
break;
default:
dctmsg(MSG_INV_TYPE);
break;
}
if (index+1 > db_ArrayList[i].ar_count)
db_ArrayList[i].ar_count = index + 1;
return index;
}
/*
* NAME:
* get_arv - get a value from an array
*
* SYNOPSIS:
* int get_arv(id, s)
* char *id; -- ASCIIZ name of array
* char *s; -- offset expression
*
* DESCRIPTION:
* Gets the value with the array id at offset s, and stores
* it into the appropriate dBASE variable.
*
* RETURNS:
* Returns index if successful, or -1 if an error occurs.
*
*/
get_arv(id, s)
char *id;
char *s;
{
int i;
int index;
/* first see if the array exists */
for (i = 0; i < MAXARRAYS; i++)
{
if (strccmp(db_ArrayList[i].ar_id, id) == 0)
break;
}
if (i == MAXARRAYS)
{
dctmsg(MSG_NO_ARRAY);
return -1;
}
index = aroff(s, db_ArrayList[i].ar_dims);
/* see if the index is valid */
if (index >= db_ArrayList[i].ar_size)
{
dctmsg(MSG_OUT_OF_BOUNDS);
return(-1);
}
switch (toupper(db_ArrayList[i].ar_type))
{
case 'C':
if (db_ArrayList[i].ar_val.vchar[index])
SetCRet(db_ArrayList[i].ar_val.vchar[index]);
break;
case 'N':
SetNRet(db_ArrayList[i].ar_val.vdub[index]);
break;
default:
dctmsg(MSG_INV_TYPE);
break;
}
return(index);
}
/*
* NAME:
* dump_array - dump contents of an array
*
* SYNOPSIS:
* dump_array(id, *f, *l)
* char *id; -- name of array
* char *f; -- offset from which to start
* char *l; -- offset of last element to dump
*
* DESCRIPTION:
* Beginning with the element whose offset is <f>, the values
* of <l> - <f> elements are displayed.
*
* RETURNS:
* Returns the number of elements in the array.
*/
dump_array(id,f,l)
char *id, *f, *l;
{
int i,j;
int first, last;
/* first see if the array exists */
for (i = 0; i < MAXARRAYS; i++)
{
if (strccmp(db_ArrayList[i].ar_id, id) == 0)
break;
}
if (i == MAXARRAYS)
{
dctmsg(MSG_NO_ARRAY);
return -1;
}
first = aroff(f, db_ArrayList[i].ar_dims);
last = aroff(l,db_ArrayList[i].ar_dims);
if (last > db_ArrayList[i].ar_size - 1)
{
dctmsg(MSG_OUT_OF_BOUNDS);
return(-1);
}
if (db_ArrayList[i].ar_count == 0)
dctmsg(MSG_EMPTY);
else for (j = first; j <= (last ? last : db_ArrayList[i].ar_count-1); j++)
{
switch (toupper(db_ArrayList[i].ar_type))
{
case 'C':
printf("%5d %s\n", j, db_ArrayList[i].ar_val.vchar[j]);
break;
case 'N':
printf("%5d %f\n",j,db_ArrayList[i].ar_val.vdub[j]);
break;
default:
dctmsg(MSG_INV_TYPE);
break;
}
if (checkkey())
break;
}
return(db_ArrayList[i].ar_count);
}
/*
* NAME:
* fdump_array - dump contents of an array to a file
*
* SYNOPSIS:
* fdump_array(id, file, *f, *l)
* char *id; -- name of array
* char *fname; -- name of file
* char *f; -- offset from which to start
* char *l; -- offset of last element to dump
*
* DESCRIPTION:
* Beginning with the element whose offset is <f>, the values
* of <l> - <f> elements are written to the text file <fname>.
* If <fname> exists, it is overwritten with the new contents.
*
* RETURNS:
* Returns the number of elements in the array.
*/
fdump_array(id,fname,f,l)
char *id, *fname, *f, *l;
{
int i,j;
int first, last;
FILE *fp;
/* first see if the array exists */
for (i = 0; i < MAXARRAYS; i++)
{
if (strccmp(db_ArrayList[i].ar_id, id) == 0)
break;
}
if (i == MAXARRAYS)
{
dctmsg(MSG_NO_ARRAY);
return -1;
}
if ((fp = fopen(fname, "w")) == 0)
{
dctmsg(MSG_IO_ERROR);
return(-1);
}
first = aroff(f, db_ArrayList[i].ar_dims);
last = aroff(l,db_ArrayList[i].ar_dims);
if (last > db_ArrayList[i].ar_size - 1)
{
dctmsg(MSG_OUT_OF_BOUNDS);
return(-1);
}
if (db_ArrayList[i].ar_count == 0)
dctmsg(MSG_EMPTY);
else for (j = first; j <= (last ? last : db_ArrayList[i].ar_count-1); j++)
{
switch (toupper(db_ArrayList[i].ar_type))
{
case 'C':
fprintf(fp, "%5d %s\n", j, db_ArrayList[i].ar_val.vchar[j]);
break;
case 'N':
fprintf(fp, "%5d %f\n",j,db_ArrayList[i].ar_val.vdub[j]);
break;
default:
dctmsg(MSG_INV_TYPE);
break;
}
if (checkkey()) /* pressing any key will abort display */
break;
}
fclose(fp);
return(db_ArrayList[i].ar_count);
}
/*
* NAME:
* st_arrays - print status of arrays
*
* SYNOPSIS:
* st_arrays();
*
* DESCRIPTION:
* Prints a summary of the status of the arrays, including
* the name, type, and size of all arrays currently in use,
* as well as the number of arrays available to the user.
*
* RETURNS:
* Returns the number of available arrays.
*
*/
extern char *BigBuf1; /* this space was grapped on start-up */
st_arrays()
{
int i,j;
int avail;
for (i = 0,avail = MAXARRAYS; i < MAXARRAYS; i++)
if (*db_ArrayList[i].ar_id)
--avail;
putwindow(1,0,(MAXARRAYS - avail)+3,79,BigBuf1);
for (i = 0,j = 0; i < MAXARRAYS; i++)
{
if (*db_ArrayList[i].ar_id) /* see if this one is used */
{
curlocat(2+j++,1);
printf(" Array: %s, Type: %c, Size: %d, Count: %d\n",
db_ArrayList[i].ar_id, db_ArrayList[i].ar_type,
db_ArrayList[i].ar_size, db_ArrayList[i].ar_count);
}
}
curlocat(MAXARRAYS-avail+2,1);
#ifdef LATTICE
printf(" There are %d arrays (and %ld bytes) available for use\n",
avail, sizmem() - ALLOC_OVHD <= 0L ?
0L : sizmem() - ALLOC_OVHD);
#else
printf(" There are %d arrays available for use\n", avail);
#endif
getkeycl(&i);
if (i != 0x1b)
rstwindo(1,0,(MAXARRAYS - avail)+3,79,BigBuf1);
return(avail);
}
/*
* NAME:
* aroff - parse an offset expression
*
* SYNOPSIS:
* int aroff(s,dims)
* char *s; -- offset expression of form d1xd2x...xdn
* int dims[]; -- array of dimension sizes
*
* DESCRIPTION:
* Calculates the actual offset of an expression, within an array
* beginning with offset 0 in each dimension.
*
* RETURNS:
* Returns the actual offset.
*
*/
aroff(s,dims)
char *s;
int *dims;
{
int size, n, i, temp;
n = 0;
size = 0;
while (*s)
{
temp = 1;
for (i = 0; i < n; i++)
temp *= dims[i];
size = atoi(s) * temp + size;
while (isdigit(*s))
s++;
if (toupper(*s) != 'X')
break;
s++;
n++;
}
return(size);
}
/*
* NAME:
* rest_arr - restore an array from disk
*
* SYNOPSIS:
* int rest_arr(id, name, start, end)
* char *id; -- ASCIIZ name of array
* char *name; -- filename to use
* char *start; -- dimension expression for first element
* char *end; -- dimensional expression for last element
*
* DESCRIPTION:
* Restores elements of the array id from the disk file name,
* beginning with <start> and ending with <end>.
* The file must have previously been created using save_arr().
*
* RETURNS:
* Returns the actual number of elements restored, which should
* normally be end-start+1, if successful, or -1 if not
*
*/
rest_arr(id, name, startexp, endexp)
char *id;
char *name;
char *startexp,*endexp;
{
int i, j;
FILE *fp;
int start, end;
char offset[6]; /* will hold actual offset for put_arv */
char value[256]; /* temp repository for element value */
/* first see if the array exists */
for (i = 0; i < MAXARRAYS; i++)
{
if (strccmp(db_ArrayList[i].ar_id, id) == 0)
break;
}
if (i == MAXARRAYS)
{
dctmsg(MSG_NO_ARRAY);
return 0;
}
start = aroff(startexp, db_ArrayList[i].ar_dims);
end = aroff(endexp, db_ArrayList[i].ar_dims);
if (start > end || end >= db_ArrayList[i].ar_size)
{
dctmsg(MSG_OUT_OF_BOUNDS);
return(0);
}
if ((fp = fopen(name, "r")) == 0)
return(-1);
/* now read in out all the elements */
for (j = start; j <= end; j++)
{
if (fgets(value, 255, fp) == NULL)
break;
value[strlen(value)-1] = '\0'; /* chop off the newline */
sprintf(offset, "%u", j);
if (put_arv(id, offset, value) < 0)
break;
}
fclose(fp);
if (j > db_ArrayList[i].ar_count)
db_ArrayList[i].ar_count = j;
return(j);
}
/*
* NAME:
* save_arr - save an array to disk
*
* SYNOPSIS:
* int save_arr(id, name, start, end)
* char *id; -- ASCIIZ name of array
* char *name; -- filename to use
* char *start; -- first element to save
* char *end; -- last element to save
*
* DESCRIPTION:
* Saves elements of the array id into a disk file, beginning
* with the <start> element and ending with <end>. If the
* file name already exists, it is written over.
*
* RETURNS:
* Returns the actual number of elements written, which should
* normally be <end>-<start>+1, if successful, or -1 if not
*
*/
save_arr(id, name, startexp, endexp)
char *id;
char *name;
char *startexp, *endexp;
{
int i,j;
int start,end;
FILE *fp;
/* first see if the array exists */
for (i = 0; i < MAXARRAYS; i++)
{
if (strccmp(db_ArrayList[i].ar_id, id) == 0)
break;
}
if (i == MAXARRAYS)
{
dctmsg(MSG_NO_ARRAY);
return 0;
}
start = aroff(startexp, db_ArrayList[i].ar_dims);
end = aroff(endexp, db_ArrayList[i].ar_dims);
if (start > end || end >= db_ArrayList[i].ar_size)
{
dctmsg(MSG_OUT_OF_BOUNDS);
return(0);
}
if ((fp = fopen(name, "w")) == 0)
return(-1);
/* now write out all the elements */
for (j = start; j <= end; j++)
{
switch (toupper(db_ArrayList[i].ar_type))
{
case 'C':
fprintf(fp, "%s\n", db_ArrayList[i].ar_val.vchar[j]);
break;
case 'N':
fprintf(fp, "%f\n", db_ArrayList[i].ar_val.vdub[j]);
break;
default:
dctmsg(MSG_INV_TYPE);
break;
}
if (ferror(fp))
return -1;
}
return(fclose(fp) < 0 ? -1 : j);
}
#ifdef LATTICE
char *dctalloc(n, size)
unsigned int n;
unsigned int size;
{
return( (long)(n*size+ALLOC_OVHD) > sizmem()
? (char *) 0 : calloc(n,size));
}
#endif